/***************************************************************************/
/*                                                                         */
/* 234218 Data Structures 1, Spring 2008                                 */
/*                                                                         */
/* Homework : Wet 2					                                       */
/*                                                                         */
/***************************************************************************/

/***************************************************************************/
/*                                                                         */
/* File Name : main2.cpp                                                   */
/*                                                                         */
/* Holds the "int main()" function and the parser of the shell's           */
/* command line.                                                           */
/***************************************************************************/


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "library2.h"


/* The command's strings */
static const char commandStr1[]			= "init";
static const char commandStr2[]	        = "attack";
static const char commandStr3[]	        = "getTown";
static const char commandStr4[]		    = "getPopeTax";
static const char commandStr5[]	        = "changePopeTax";
static const char commandStr6[]		    = "changeSalary";
static const char commandStr7[]		    = "quit";


/* we assume maximum string size is not longer than 256  */
#define  MAX_STRING_INPUT_SIZE (255)
#define StrCmp(Src1,Src2) (0 == strncmp(Src1,Src2,strlen(Src1)) )


typedef enum {error_free, error} errorType;

static errorType parser(char *command);

#define ValidateRead(read_parameters,required_parameters,ErrorString) if(read_parameters!=required_parameters){printf(ErrorString);return error;}


bool is_init = false;
bool is_imp_bonus = false;

/***************************************************************************/
/* main			                                                           */
/***************************************************************************/
int main() {

	char buffer[MAX_STRING_INPUT_SIZE];
   
	// Reading commands
	while ( NULL != fgets(buffer, MAX_STRING_INPUT_SIZE, stdin) ) {
		fflush(stdout); 
		if ( error == parser(buffer) ) return 0;
	};
	return 0;
}


/***************************************************************************/
/* Parser                                                                  */
/***************************************************************************/

static errorType parser(char *command) { 
	
	static void *structure = NULL; /* The general data structure */
	
	char str[MAX_STRING_INPUT_SIZE];
	
	if ( NULL == command )         return error_free;
	if ( 0    == strlen(command) ) return error_free;
	if ( StrCmp("\n", command)   ) return error_free;

	// On init.	
	if ( StrCmp(commandStr1, command) ) {
		if( is_init )
		{
			printf("Init was already called.\n");
			return error_free;			
		}
		is_init = true;

		int n(0), defaultSalary(0);
		ValidateRead( sscanf(command, "%s %d %d", str, &n, &defaultSalary), 3, "Init failed.\n" );
		structure = init(n, defaultSalary);
		if( structure == NULL ) {
			printf("Init failed.\n");
			return error;
		}
		printf("Init succeeded.\n");

		return error_free;
	}

	// attack
	if ( StrCmp(commandStr2, command) ) { 
		int town1, town2;
		ValidateRead( sscanf(command, "%s %d %d", str, &town1, &town2), 3, "Attack function failed.\n" );
		int res = attack(structure, town1, town2);
		if ( res >= SUCCESS )
			printf("Town %d conquered town %d\n", town1, town2);
		else
			printf("Attack failed with error %d.\n", res);
		return error_free;
	}
	
	// get town
	if ( StrCmp(commandStr3, command) ) { 
		int id, townId;
		ValidateRead( sscanf(command, "%s %d", str, &id), 2, "Get town failed.\n" );
         
		int res = getTown( structure, id, &townId);
		if ( res >= SUCCESS ) {
			printf("Citizen %d lives in town %d\n", id, townId);
		}
		else
			printf("Get town failed with error %d.\n", res);
		return error_free;
	}
	
	// get pope tax
	if ( StrCmp(commandStr4, command) ) { 
		int town, tax;
		ValidateRead( sscanf(command, "%s %d", str, &town), 2, "Get pope tax failed.\n" );
         
		int res = getPopeTax(structure, town, &tax);
		if ( res >= SUCCESS )
			printf("Town %d pays %d to the pope\n", town, tax);
		else
			printf("Get pope tax failed with error %d.\n", res);
		return error_free;
	}
	
	// change pope tax
	if ( StrCmp(commandStr5, command) ) { 
		int townFrom, townTo, additionalTax;
		ValidateRead( sscanf(command, "%s %d %d %d", str, &townFrom, &townTo, &additionalTax),
			4, "Change pope tax failed.\n" );
         
		int res = changePopeTax(structure, townFrom, townTo, additionalTax);
		if (  res >= SUCCESS )
			printf("Changed pope tax for towns betwen %d and %d by %d\n",  townFrom, townTo, additionalTax);
		else
			printf("Change pope tax failed with error %d.\n", res);
		return error_free;
	}

	// change salary
	if ( StrCmp(commandStr6, command) ) { 
		int town, newSalary;
		ValidateRead( sscanf(command, "%s %d %d", str, &town, &newSalary),
			3, "Change salary failed.\n" );
         
		int res = changeSalary(structure, town, newSalary);
		if (  res >= SUCCESS )
			printf("Changed salary of town %d to %d\n",  town, newSalary);
		else
			printf("Change salary failed with error %d.\n", res);
		return error_free;
	}

	// quit 
	if ( StrCmp(commandStr7, command) ) {  
		quit(structure);
		printf("Closing...\n");
		return error_free;
	}
	
	// else
	printf( "Unknown command: %s\n", command );
	return error;
}
